package cn.com.jsr.translation.termidentifier;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 术语查找器
 */
public abstract class Seeker{
	private static Logger logger = LoggerFactory.getLogger(Seeker.class);
	
	/** 区分大小写 */
	public static final int CASE_INSENSITIVE = 0B00000001;
	
	/** 合并空白（即，当术语为多个单词构成的词组时，单词之间的空白无论多少均可识别） */
	public static final int MERGE_BLANK = 0B00000010;
	
	protected Dictionary dictionary = new Dictionary();
	
	/**
	 * 获取字典
	 * @return
	 */
	public Dictionary getDictionary(){
		return dictionary;
	}

	/**
	 * 设置字典
	 * @param dictionary
	 */
	public void setDictionary(Dictionary dictionary){
		this.dictionary = dictionary;
	}

	/**
	 * 捕获到术语时执行的方法。其返回结果将代替术语在原文中的位置
	 * @param content 捕获到的内容
	 * @param term 捕获内容时对应的术语
	 * @param policy 捕获内容时采取的策略
	 * @return 处理后的结果
	 */
	public abstract String onmatch(String content, String term, int policy);
	
	/**
	 * 根据提供的原文和策略查找术语，并返回处理后的结果
	 * @param src 英文原文
	 * @param policy 术语匹配策略
	 * @return 处理后的结果
	 */
	public String seek(String src, int policy){
		if(null == src)
			return null;
		
		boolean mergeBlanks = (Seeker.MERGE_BLANK & policy) == Seeker.MERGE_BLANK;
		boolean ignoreCase = (Seeker.CASE_INSENSITIVE & policy) == Seeker.CASE_INSENSITIVE;
		
		List<String> terms = dictionary.listTerms();
		/* 排序字典，使得包含其他术语的术语优先处理 */
		terms.sort((a, b) ->{
			if(a.toLowerCase().contains(b.toLowerCase())){
				return -1;
			}else if(b.toLowerCase().contains(a.toLowerCase()))
				return 1;
			else
				return 0;
		});
		String parsed = src;
		
		for(String term: terms){
			int lastIndex = 0;
			String tmpParsed = "";
			
			/* 根据策略构造正则表达式 */
			String expected = !mergeBlanks? term: Arrays.asList(term.split("\\s+")).stream().collect(Collectors.joining("\\s+"));;
			
			String r = "\\b" + expected + "\\b";
			Pattern p = ignoreCase? Pattern.compile(r, Pattern.CASE_INSENSITIVE): Pattern.compile(r);
			
			/* 使用上一轮的输出作为新一轮的输入 */
			Matcher m = p.matcher(parsed);
			while(m.find()){
				String group = m.group();
				int index = m.start();
				int groupLength = group.length();
				
				group = group.replaceAll("\\s+", " ");
				/* 调用匹配方法 */
				String result = onmatch(group, term, policy);
				
				/* 如果返回为null，则使用术语替代，不做翻译 */
				if(null == result){
					result = group;
					logger.warn("Fail to get translation for captured content: {}(term: {}), no action will be performed!", group, term);
				}
				
				tmpParsed += parsed.substring(lastIndex, index);
				tmpParsed += result;
				
				lastIndex = index + groupLength;
			}
			if(lastIndex <= parsed.length() - 1)
				tmpParsed += parsed.substring(lastIndex);
			
			/* 更新结果为此轮输出 */
			parsed = tmpParsed;
		}
		
		return parsed;
	}
	
	/**
	 * 根据提供的原文，以“区分空白个数、区分大小写”策略查找术语，并返回处理后的结果
	 * @param src 英文原文
	 * @return 处理后的结果
	 */
	public String seek(String src){
		return seek(src, 0);
	}
}
